#region license
/*
 * Copyright (C) 2007 CchenSoft.com
 * 
 * This library is free software; you can redistribute it and/or modify it 
 * under the terms of the GNU Lesser General Public License 2.1 or later, as
 * published by the Free Software Foundation. See the included License.txt
 * or http://www.gnu.org/copyleft/lesser.html for details.
 * 
 * Author: Billy Zhang
 */
#endregion

using System.Collections;
using System.Xml;
using System.Collections.Generic;

namespace CchenSoft.Workflow.Loader
{
    public class ConditionalResultDescriptor : ResultDescriptor
    {
        //~ Instance fields ////////////////////////////////////////////////////////

        protected List<BaseConditionDescriptor> conditions = new List<BaseConditionDescriptor>();

        //~ Constructors ///////////////////////////////////////////////////////////

        /**
         * @deprecated use {@link DescriptorFactory} instead
         */
        public ConditionalResultDescriptor()
        {
        }

        /**
         * @deprecated use {@link DescriptorFactory} instead
         */
        public ConditionalResultDescriptor(XmlElement conditionalResult)
        {
            Init(conditionalResult);
        }

        //~ Methods ////////////////////////////////////////////////////////////////

        public IList<BaseConditionDescriptor> Conditions
        {
            get { return conditions; }
        }

        public string GetDestination()
        {
            WorkflowDescriptor desc = null;
            string sName = "";
            AbstractDescriptor actionDesc = Parent.Parent;

            if (actionDesc != null)
            {
                desc = (WorkflowDescriptor)actionDesc.Parent;
            }

            if (join != 0)
            {
                return "join #" + join;
            }
            else if (split != 0)
            {
                return "split #" + split;
            }
            else
            {
                if (desc != null)
                {
                    sName = desc.GetStep(step).Name;
                }

                return "step #" + step + " [" + sName + "]";
            }
        }

        public override void Validate()
        {
            base.Validate();

            if (conditions.Count == 0)
            {
                throw new InvalidWorkflowDescriptorException("Conditional result from " + ((ActionDescriptor)Parent).Name + " to " + GetDestination() + " must have at least one condition");
            }

            ValidationHelper.Validate((ICollection<IValidatable>)conditions);
        }

        public override void WriteXML(XmlTextWriter writer, int indent)
        {
            XMLUtil.printIndent(writer, indent++);

            writer.WriteStartElement("result");

            if (HasId())
            {
                //buf.append(" id=\"").append(getId()).append('\"');
                writer.WriteAttributeString("id", Id.ToString());
            }

            if ((dueDate != null) && (dueDate.Length > 0))
            {
                //buf.append(" due-date=\"").append(getDueDate()).append('\"');
                writer.WriteAttributeString("due-date", dueDate);
            }

            //buf.append(" old-status=\"").append(oldStatus).append('\"');
            writer.WriteAttributeString("old-status", oldStatus);

            if (join != 0)
            {
                //buf.append(" join=\"").append(join).append('\"');
                writer.WriteAttributeString("join", join.ToString());
            }
            else if (split != 0)
            {
                //buf.append(" split=\"").append(split).append('\"');
                writer.WriteAttributeString("split", split.ToString());
            }
            else
            {
                //buf.append(" status=\"").append(status).append('\"');
                writer.WriteAttributeString("status", status);

                //buf.append(" step=\"").append(step).append('\"');
                writer.WriteAttributeString("step", step.ToString());

                if ((owner != null) && (owner.Length > 0))
                {
                    //buf.append(" owner=\"").append(owner).append('\"');
                    writer.WriteAttributeString("owner", owner);
                }

                if ((displayName != null) && (displayName.Length > 0))
                {
                    //buf.append(" display-name=\"").append(displayName).append('\"');
                    writer.WriteAttributeString("display-name", displayName);
                }
            }

            for (int i = 0; i < conditions.Count; i++)
            {
                ConditionsDescriptor condition = (ConditionsDescriptor)conditions[i];
                condition.WriteXML(writer, indent);
            }

            if (validators.Count > 0)
            {
                XMLUtil.printIndent(writer, indent++);
                writer.WriteStartElement("validators");

                for (int i = 0; i < validators.Count; i++)
                {
                    ValidatorDescriptor validator = (ValidatorDescriptor)validators[i];
                    validator.WriteXML(writer, indent);
                }

                XMLUtil.printIndent(writer, --indent);
                writer.WriteEndElement(); //("</validators>");
            }

            printPreFunctions(writer, indent);
            printPostFunctions(writer, indent);
            XMLUtil.printIndent(writer, --indent);

            writer.WriteEndElement(); // ("</result>");
        }

        protected override void Init(XmlElement conditionalResult)
        {
            base.Init(conditionalResult);

            XmlNodeList conditionNodes = conditionalResult.SelectNodes("conditions");

            int length = conditionNodes.Count;

            for (int i = 0; i < length; i++)
            {
                XmlElement condition = (XmlElement)conditionNodes[i];
                ConditionsDescriptor conditionDescriptor = DescriptorFactory.GetFactory().CreateConditionsDescriptor(condition);
                conditionDescriptor.Parent = this;
                this.conditions.Add(conditionDescriptor);
            }
        }
    }
}
